home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Mail / Sources / UMailable.cp next >
Encoding:
Text File  |  1996-04-03  |  59.0 KB  |  1,873 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UMailable.cp 
  3. // Copyright © 1984-96 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #if qPowerTalk
  7.  
  8. #ifndef __UMAILABLE__
  9. #include "UMailable.h"
  10. #endif
  11.  
  12. // MacApp
  13.  
  14. #ifndef __UAPPLEEVENTS__
  15. #include "UAppleEvents.h"
  16. #endif
  17.  
  18. #ifndef __UAPPLICATION__
  19. #include "UApplication.h"
  20. #endif
  21.  
  22. #ifndef __UDISPATCHER__
  23. #include "UDispatcher.h"
  24. #endif
  25.  
  26. #ifndef __UDOCUMENT__
  27. #include "UDocument.h"
  28. #endif
  29.  
  30. #ifndef __UERRORMGR__
  31. #include "UErrorMgr.h"
  32. #endif
  33.  
  34. #ifndef __UFILE__
  35. #include "UFile.h"
  36. #endif
  37.  
  38. #ifndef __UMACAPPGLOBALS__
  39. #include "UMacAppGlobals.h"
  40. #endif
  41.     
  42. #ifndef __UMACAPPUTILITIES__
  43. #include "UMacAppUtilities.h"
  44. #endif
  45.     
  46. #ifndef __UMAILER__
  47. #include "UMailer.h"
  48. #endif
  49.  
  50. #ifndef __UMAILERVIEW__
  51. #include "UMailerView.h"
  52. #endif
  53.  
  54. #ifndef __UMEMORY__
  55. #include "UMemory.h"
  56. #endif
  57.  
  58. #ifndef __UMENUMGR__
  59. #include "UMenuMgr.h"
  60. #endif
  61.  
  62. #ifndef __UOBJECT__
  63. #include "UObject.h"
  64. #endif
  65.  
  66. #ifndef __USCRIPTING__
  67. #include "UScripting.h"
  68. #endif
  69.  
  70. #ifndef __UWINDOW__
  71. #include "UWindow.h"
  72. #endif
  73.  
  74. // Toolbox
  75.  
  76. #ifndef __AEREGISTRY__
  77. #include <AERegistry.h>
  78. #endif
  79.  
  80. #if qPowerPC || qModelCFM
  81.     #ifndef __FRAGLOAD__
  82.     #include <FragLoad.h>
  83.     #endif
  84. #endif
  85.  
  86. #ifndef __OCESTANDARDDIRECTORY__
  87. #include <OCEStandardDirectory.h>
  88. #endif
  89.  
  90. #ifndef __OCEERRORS__
  91. #include <OCEErrors.h>
  92. #endif
  93.  
  94. // ANSI
  95.  
  96. #ifndef __STDIO__
  97. #include <stdio.h>
  98. #endif
  99.  
  100. //========================================================================================
  101. // GLOBAL Variables
  102. //========================================================================================
  103.  
  104. MMailing* gMailing;
  105.  
  106. //========================================================================================
  107. // CLASS CDirExtTypeTableIterator
  108. //========================================================================================
  109.  
  110. #if PRAGMA_ALIGN_SUPPORTED
  111. #pragma options align=mac68k
  112. #endif
  113.  
  114. struct DirExtTypeEntry
  115. {
  116.     OSType extType;
  117.     Boolean isRString;
  118.     char fill1;
  119.     char fill2;
  120.     char fill3;
  121.     CStr255 dirSysName;
  122. };
  123.  
  124. struct DirExtTypeTable
  125. {
  126.     short count;
  127.     DirExtTypeEntry dirExtTypeDesc;
  128. };
  129.  
  130. #if PRAGMA_ALIGN_SUPPORTED
  131. #pragma options align=reset
  132. #endif
  133.  
  134. class CDirExtTypeTableIterator
  135. {
  136.     long fCurrentIndex;
  137.     long fNumOfExtTypes;
  138.     DirExtTypeTable** fDirExtTypeTable;
  139.     long fCurrentOffset;                        // offset to the current rstring in the resource.
  140.  
  141.   public:
  142.     CDirExtTypeTableIterator(short resID);
  143.  
  144.     DirExtTypeEntry* FirstDirExtType();
  145.     Boolean More();
  146.     DirExtTypeEntry* NextDirExtType();
  147. };
  148.  
  149. inline Boolean CDirExtTypeTableIterator::More(){ return fCurrentIndex <= fNumOfExtTypes; };
  150.  
  151. //--------------------------------------------------------------------------------------------------
  152. // CDirExtTypeTableIterator::CDirExtTypeTableIterator
  153. //--------------------------------------------------------------------------------------------------
  154.  
  155. CDirExtTypeTableIterator::CDirExtTypeTableIterator(short resID)
  156. {
  157.     fCurrentIndex = 0;
  158.     fNumOfExtTypes = 0;
  159.     fCurrentOffset = 0;
  160.  
  161.     fDirExtTypeTable = (DirExtTypeTable**)MAGet1Resource('dxtt', resID);
  162.     FailNILResource((Handle)fDirExtTypeTable);
  163.  
  164.     MoveHHi((Handle)fDirExtTypeTable);
  165.     HLock((Handle)fDirExtTypeTable);            //     we assume its locked down.
  166.  
  167.     if (fDirExtTypeTable == 0)
  168.         return;
  169.  
  170.     fNumOfExtTypes = (*fDirExtTypeTable)->count;
  171. }
  172.  
  173. //--------------------------------------------------------------------------------------------------
  174. // CDirExtTypeTableIterator::FirstDirExtType
  175. //--------------------------------------------------------------------------------------------------
  176.  
  177. DirExtTypeEntry* CDirExtTypeTableIterator::FirstDirExtType()
  178. {
  179.     fCurrentIndex = 1;
  180.     fCurrentOffset = 0;
  181.     if (More())
  182.         return (DirExtTypeEntry *)(((char*) & (*fDirExtTypeTable)->dirExtTypeDesc) + fCurrentOffset);
  183.  
  184.     return 0;
  185. }
  186.  
  187. //--------------------------------------------------------------------------------------------------
  188. // CDirExtTypeTableIterator::NextDirExtType
  189. //--------------------------------------------------------------------------------------------------
  190.  
  191. DirExtTypeEntry* CDirExtTypeTableIterator::NextDirExtType()
  192. {
  193.     fCurrentIndex++;
  194.     if (More())
  195.     {
  196.         DirExtTypeEntry* dirExtType = (DirExtTypeEntry*)(((char*) & (*fDirExtTypeTable)->dirExtTypeDesc) + fCurrentOffset);
  197.  
  198.         fCurrentOffset += sizeof(OSType) + 4 + dirExtType->dirSysName[0] + 1;    // the size of each entry
  199.  
  200.         fCurrentOffset += (fCurrentOffset & 1);    //    align it.
  201.  
  202.         return (DirExtTypeEntry *)(((char*) & (*fDirExtTypeTable)->dirExtTypeDesc) + fCurrentOffset);
  203.     }
  204.  
  205.     return 0;
  206. }
  207.  
  208. //========================================================================================
  209. // CLASS CCatalogs
  210. //========================================================================================
  211.  
  212. //--------------------------------------------------------------------------------------------------
  213. // CCatalogs::CCatalogs
  214. //--------------------------------------------------------------------------------------------------
  215.  
  216. CCatalogs::CCatalogs()
  217.     : fForEachDirectoryProc(NULL),
  218.       fClientData(0),
  219.       fDirectoryNameToFind(NULL),
  220.       fCatalogFound(FALSE)
  221. {
  222.     fStartingDirDiscriminator.signature = 0;
  223.     fStartingDirDiscriminator.misc = 0;
  224.     fFoundDirDiscriminator.signature = 0;
  225.     fFoundDirDiscriminator.misc = 0;
  226. }
  227.  
  228. //--------------------------------------------------------------------------------------------------
  229. // CCatalogs::EachDirectoryGlue
  230. //--------------------------------------------------------------------------------------------------
  231.  
  232. Boolean CCatalogs::EachCatalogGlue(long clientData,
  233.                                    const DirectoryName* dirName,
  234.                                    const DirDiscriminator* discriminator,
  235.                                    DirGestalt features)
  236. {
  237.     Boolean done = TRUE;
  238.     CCatalogs * theCatalogs = (CCatalogs *)clientData;
  239.     ForEachDirectory myForEachDirectoryProc = theCatalogs->fForEachDirectoryProc;
  240.     if (myForEachDirectoryProc)
  241.     {
  242.         FailInfo fi;
  243.         Try(fi)
  244.         {
  245.             done = CallForEachDirectoryProc(myForEachDirectoryProc, clientData, dirName, discriminator, features);
  246.             fi.Success();
  247.         }
  248.         else
  249.             done = TRUE;
  250.     }
  251.     OCECopyRString((RStringPtr)dirName, (RStringPtr)&theCatalogs->fStartingDirectoryName, kRStringMaxBytes);
  252.     theCatalogs->fStartingDirDiscriminator = *discriminator;
  253.     return done;
  254. }
  255.  
  256. //--------------------------------------------------------------------------------------------------
  257. // CCatalogs::EnumerateCatalogs
  258. //--------------------------------------------------------------------------------------------------
  259.  
  260. void CCatalogs::EnumerateCatalogs(OCEDirectoryKind catalogType,
  261.                                   ForEachDirectory actionProc)
  262. {
  263.     const long     kGetBufferSize = 1024;
  264.     
  265.     Boolean    result = FALSE;
  266.     OSErr    getErr = kOCEMoreData;
  267.     OSErr    parseErr = kOCEMoreData;
  268.     DirEnumerateDirectoriesGetPB     getPB;
  269.     DirEnumerateDirectoriesParsePB     parsePB;
  270.     ForEachDirectory                 eachCatalogProc = NULL;
  271.     
  272.     fForEachDirectoryProc = actionProc;
  273.     getPB.getBuffer = NULL;
  274.     
  275.     FailInfo fi;
  276.     Try(fi)
  277.     {        
  278.         BlockSet((Ptr)&fStartingDirectoryName, sizeof(DirectoryName), 0);
  279.         eachCatalogProc = NewForEachDirectoryProc(EachCatalogGlue);
  280.         FailNIL(eachCatalogProc);
  281.         
  282.         getPB.ioCompletion = NULL;
  283.         getPB.clientData = (long)this;
  284.         getPB.directoryKind = catalogType;
  285.         getPB.getBuffer = NewPermPtr(kGetBufferSize);    // allocate the buffer
  286.         FailNIL(getPB.getBuffer);
  287.         getPB.getBufferSize = kGetBufferSize;
  288.         
  289.         parsePB.ioCompletion = NULL;
  290.         parsePB.clientData = (long)this;
  291.         parsePB.eachDirectory = eachCatalogProc;
  292.         parsePB.getBuffer = getPB.getBuffer;
  293.         parsePB.getBufferSize = kGetBufferSize;
  294.         
  295.         while ((getErr == kOCEMoreData) || (parseErr == kOCEMoreData))
  296.         {
  297.             getErr = DirEnumerateDirectoriesGet((DirParamBlockPtr)&getPB, FALSE);
  298.             parseErr = DirEnumerateDirectoriesParse((DirParamBlockPtr)&parsePB, FALSE);
  299.             getPB.includeStartingPoint = FALSE;
  300.             getPB.startingDirectoryName = &fStartingDirectoryName;
  301.             getPB.startingDirDiscriminator = fStartingDirDiscriminator;
  302.         }
  303.         
  304.         getPB.getBuffer = DisposeIfPtr(getPB.getBuffer);
  305.         eachCatalogProc = DisposeIfRoutineDescriptor(eachCatalogProc);
  306.         FailOSErr(getErr);
  307.         FailOSErr(parseErr);
  308.         fi.Success();
  309.     }
  310.     else // Recover
  311.     {
  312.         getPB.getBuffer = DisposeIfPtr(getPB.getBuffer);
  313.         eachCatalogProc = DisposeIfRoutineDescriptor(eachCatalogProc);
  314.         fi.ReSignal();
  315.     }
  316. }
  317.  
  318. //--------------------------------------------------------------------------------------------------
  319. // CCatalogs::FindCatalogByNameProc
  320. //--------------------------------------------------------------------------------------------------
  321.  
  322. Boolean CCatalogs::FindCatalogByNameProc(long clientData,
  323.                                          const DirectoryName* dirName,
  324.                                          const DirDiscriminator* discriminator,
  325.                                          DirGestalt/*features*/ )
  326. {
  327.     CCatalogs * theCatalogs = (CCatalogs *)clientData;
  328.     if (OCEEqualRString(dirName, theCatalogs->fDirectoryNameToFind, kOCEDirName))
  329.     {
  330.         theCatalogs->fFoundDirDiscriminator = *discriminator;
  331.         theCatalogs->fCatalogFound = TRUE;
  332.     }
  333.     return theCatalogs->fCatalogFound;
  334. }
  335.  
  336. //--------------------------------------------------------------------------------------------------
  337. // CCatalogs::FindCatalogByName
  338. //--------------------------------------------------------------------------------------------------
  339.  
  340. Boolean CCatalogs::FindCatalogByName(DirectoryNamePtr theCatalogName,
  341.                                      OCEDirectoryKind catalogType,
  342.                                      DirDiscriminator& discriminator)
  343. {
  344.     Boolean foundIt = FALSE;
  345.     fCatalogFound = FALSE;
  346.     fDirectoryNameToFind = theCatalogName;
  347.     ForEachDirectory findCatalogProc = NewForEachDirectoryProc(FindCatalogByNameProc);
  348.     FailInfo fi;
  349.     Try(fi)
  350.     {
  351.         this->EnumerateCatalogs(catalogType, findCatalogProc);
  352.         foundIt = fCatalogFound;
  353.         if (foundIt)
  354.             discriminator = fFoundDirDiscriminator;
  355.         fi.Success();
  356.     }
  357.     else
  358.         foundIt = FALSE;
  359.     DisposeRoutineDescriptor((UniversalProcPtr)findCatalogProc);
  360.     return foundIt;
  361. }
  362.  
  363. //========================================================================================
  364. // CLASS CDSSpec
  365. //========================================================================================
  366.  
  367. //--------------------------------------------------------------------------------------------------
  368. // CDSSpec::CDSSpec
  369. //--------------------------------------------------------------------------------------------------
  370.  
  371. CDSSpec::CDSSpec()
  372. {
  373.     fPackedDSSpec = NULL;
  374.     fUnpacked = FALSE;
  375. }
  376.  
  377. //--------------------------------------------------------------------------------------------------
  378. // CDSSpec::CDSSpec(PackedDSSpecPtr* aPackedDSSpec)
  379. //--------------------------------------------------------------------------------------------------
  380.  
  381. CDSSpec::CDSSpec(PackedDSSpecPtr aPackedDSSpec)
  382. {
  383.     long theSize = sizeof(ProtoPackedDSSpec) + aPackedDSSpec->dataLength;
  384.     fPackedDSSpec = (PackedDSSpecPtr)NewPtr(theSize);
  385.     MABlockMove((Ptr)aPackedDSSpec, (Ptr)fPackedDSSpec, theSize);
  386.     this->Unpack();
  387. }
  388.  
  389. //--------------------------------------------------------------------------------------------------
  390. // CDSSpec::CDSSpec(const CAEDesc& anAEDesc)
  391. //--------------------------------------------------------------------------------------------------
  392.  
  393. CDSSpec::CDSSpec(const CAEDesc& anAEDesc)
  394. {
  395.     long theSize = anAEDesc.GetDataSize();
  396.     fPackedDSSpec = (PackedDSSpecPtr)NewPtr(theSize);
  397.     MABlockMove(*anAEDesc.GetDataHandle(), (Ptr)fPackedDSSpec, theSize);
  398.     this->Unpack();
  399. }
  400.  
  401. //--------------------------------------------------------------------------------------------------
  402. // CDSSpec::~CDSSpec
  403. //--------------------------------------------------------------------------------------------------
  404.  
  405. CDSSpec::~CDSSpec()
  406. {
  407.     fPackedDSSpec = (PackedDSSpecPtr)DisposeIfPtr((Ptr)fPackedDSSpec);
  408. }
  409.  
  410. //--------------------------------------------------------------------------------------------------
  411. // CDSSpec::Unpack
  412. //--------------------------------------------------------------------------------------------------
  413.  
  414. Boolean CDSSpec::Unpack()
  415. {
  416.     if (fPackedDSSpec)
  417.     {
  418.         unsigned short nodeCount = 0;
  419.         if (OCEValidPackedDSSpec(fPackedDSSpec))
  420.         {
  421.             OCEUnpackDSSpec(fPackedDSSpec, &fDSSpec, &fRecordID);
  422.             if (OCEValidPackedRLI(fRecordID.rli))
  423.             {
  424.                 OCEUnpackRLI(fRecordID.rli, &fRLI);
  425.                 fUnpacked = TRUE;
  426.             }
  427.         }
  428.     }
  429.     return fUnpacked;
  430. }
  431.  
  432. //--------------------------------------------------------------------------------------------------
  433. // CDSSpec::Pack
  434. //--------------------------------------------------------------------------------------------------
  435.  
  436. void CDSSpec::Pack()
  437. {
  438.     long theSize = OCEPackedRLISize(&fRLI);
  439.     PackedRLIPtr thePackedRLI = (PackedRLIPtr)NewPtr(theSize);
  440.     OCEPackRLI(&fRLI, thePackedRLI, theSize);
  441.     fRecordID.rli = thePackedRLI;
  442.     theSize = OCEPackedDSSpecSize(&fDSSpec);
  443.     fPackedDSSpec = (PackedDSSpecPtr)DisposeIfPtr((Ptr)fPackedDSSpec);
  444.     fPackedDSSpec = (PackedDSSpecPtr)NewPtr(theSize);
  445.     FailOSErr(OCEPackDSSpec(&fDSSpec, fPackedDSSpec, theSize));
  446.     DisposeIfPtr((Ptr)thePackedRLI);
  447. }
  448.  
  449. //--------------------------------------------------------------------------------------------------
  450. // CDSSpec::GetExtensionType
  451. //--------------------------------------------------------------------------------------------------
  452.  
  453. OSType CDSSpec::GetExtensionType()
  454. {
  455.     if (fUnpacked)
  456.         return this->fDSSpec.extensionType;
  457.     else if (fPackedDSSpec)
  458.         return OCEGetExtensionType(fPackedDSSpec);
  459.     else
  460.         return '\?\?\?\?';
  461. }
  462.  
  463. //--------------------------------------------------------------------------------------------------
  464. // CDSSpec::GetExtensionValue
  465. //--------------------------------------------------------------------------------------------------
  466.  
  467. void CDSSpec::GetPathName(CStr255& thePathName)
  468. {
  469.     DirParamBlockPtr pb = (DirParamBlockPtr)NewPtrClear(sizeof(DirParamBlock));
  470.     PackedPathNamePtr packedPathName = (PackedPathNamePtr)NewPtrClear(kPathNameMaxBytes);
  471.     gMailing->GetAOCEIdentity(pb->mapDNodeNumberToPathNamePB.identity, FALSE);
  472.     pb->mapDNodeNumberToPathNamePB.directoryName = this->fRLI.directoryName;
  473.     pb->mapDNodeNumberToPathNamePB.discriminator = this->fRLI.discriminator;
  474.     pb->mapDNodeNumberToPathNamePB.dNodeNumber = this->fRLI.dNodeNumber;
  475.     pb->mapDNodeNumberToPathNamePB.path = packedPathName;
  476.     pb->mapDNodeNumberToPathNamePB.lengthOfPathName = kPathNameMaxBytes;
  477.     OSErr anErr = DirMapDNodeNumberToPathName(pb, FALSE);
  478.     if (anErr == noErr)
  479.     {
  480.         thePathName = this->GetDirectoryName();
  481.         RStringPtr parts[16];
  482.         unsigned short numParts = OCEUnpackPathName(packedPathName, parts, 16);
  483.         while (numParts)
  484.         {
  485.             CStr255 pathPart = OCERToPString(parts[--numParts]);
  486.             thePathName += ':';
  487.             thePathName += pathPart;
  488.         }
  489.     }
  490.     DisposeIfPtr((Ptr)pb);
  491.     DisposeIfPtr((Ptr)packedPathName);
  492. }
  493.  
  494. //--------------------------------------------------------------------------------------------------
  495. // CDSSpec::GetAEDesc(CAEDesc& theAEDesc)
  496. //--------------------------------------------------------------------------------------------------
  497.  
  498. void CDSSpec::GetAEDesc(CAEDesc& theAEDesc)
  499. {
  500.     if (fPackedDSSpec)
  501.     {
  502.         theAEDesc.CreateDesc(typePackedDSSpec, (Ptr)fPackedDSSpec, sizeof(ProtoPackedDSSpec) + fPackedDSSpec->dataLength);
  503.     }
  504. }
  505.  
  506. //--------------------------------------------------------------------------------------------------
  507. // CDSSpec::UnpackDirectDialupInfo
  508. //--------------------------------------------------------------------------------------------------
  509.  
  510. PhoneNumberInfo* CDSSpec::UnpackDirectDialupInfo()
  511. {
  512.     if (!fUnpacked)
  513.         return NULL;
  514.     PhoneNumberInfo * phoneInfo = (PhoneNumberInfo *)NewPtr(sizeof(PhoneNumberInfo));
  515.     Ptr ext = (Ptr)(fDSSpec.extensionValue + sizeof(ProtoRString));
  516.     phoneInfo->fSubType = *(short*)ext;
  517.     ext += sizeof(short);
  518.     phoneInfo->fCountryCode = UnpackRString(ext);
  519.     phoneInfo->fAreaCode = UnpackRString(ext);
  520.     phoneInfo->fPhoneNumber = UnpackRString(ext);
  521.     phoneInfo->fPostFix = UnpackRString(ext);
  522.     phoneInfo->fDirectDial = UnpackRString(ext);
  523.     return phoneInfo;
  524. }
  525.  
  526. //--------------------------------------------------------------------------------------------------
  527. // CDSSpec::UnpackSTFFaxInfo
  528. //--------------------------------------------------------------------------------------------------
  529.  
  530. PhoneNumberInfo* CDSSpec::UnpackSTFFaxInfo()
  531. {
  532.     if (!fUnpacked)
  533.         return NULL;
  534.     PhoneNumberInfo * phoneInfo = (PhoneNumberInfo *)NewPtr(sizeof(PhoneNumberInfo));
  535.     Ptr ext = (Ptr)(fDSSpec.extensionValue);
  536.     phoneInfo->fDirectDial = UnpackRString(ext);
  537.     phoneInfo->fCountryCode = UnpackRString(ext);
  538.     phoneInfo->fAreaCode = UnpackRString(ext);
  539.     phoneInfo->fPhoneNumber = UnpackRString(ext);
  540.     phoneInfo->fPostFix = UnpackRString(ext);
  541.     phoneInfo->fSubType = (short) * (long*)ext;
  542.     return phoneInfo;
  543. }
  544.  
  545. //--------------------------------------------------------------------------------------------------
  546. // CDSSpec::PackString
  547. //--------------------------------------------------------------------------------------------------
  548.  
  549. void CDSSpec::PackString(Ptr& packIn,
  550.                 const CStr31& theStr)
  551. {
  552.     long theSize = theStr.Length() + 1;
  553.     MABlockMove(&theStr, packIn, theSize);
  554.     if (theSize % 2)                            // odd number string, add the padding
  555.         theSize++;
  556.     packIn += theSize;
  557. }
  558.  
  559. //--------------------------------------------------------------------------------------------------
  560. // CDSSpec::PackRString
  561. //--------------------------------------------------------------------------------------------------
  562.  
  563. void CDSSpec::PackRString(Ptr& packIn,
  564.                  const CStr31& theStr)
  565. {
  566.     RString theRStr;
  567.     OCEPToRString(theStr, smRoman, &theRStr, kRStringMaxBytes);
  568.     long theSize = theRStr.dataLength + sizeof(ProtoRString);
  569.     MABlockMove(&theRStr, packIn, theSize);
  570.     if (theSize % 2)                            // odd number string, add the padding
  571.         theSize++;
  572.     packIn += theSize;
  573. }
  574.  
  575. //--------------------------------------------------------------------------------------------------
  576. // CDSSpec::PackRString
  577. //--------------------------------------------------------------------------------------------------
  578.  
  579. void CDSSpec::PackRString(Ptr& packIn,
  580.                  RStringPtr theStr)
  581. {
  582.     long theSize = theStr->dataLength + sizeof(ProtoRString);
  583.     MABlockMove(theStr, packIn, theSize);
  584.     if (theSize % 2)                            // odd number string, add the padding
  585.         theSize++;
  586.     packIn += theSize;
  587. }
  588.  
  589. //--------------------------------------------------------------------------------------------------
  590. // CDSSpec::UnpackRString
  591. //--------------------------------------------------------------------------------------------------
  592.  
  593. StringPtr CDSSpec::UnpackRString(Ptr& unpackFrom)
  594. {
  595.     StringPtr result = OCERToPString((RStringPtr)unpackFrom);
  596.     unpackFrom = unpackFrom + ((RStringPtr)unpackFrom)->dataLength + sizeof(ProtoRString);
  597.     if (result[0] % 2)                            // odd number string, skip the padding
  598.         unpackFrom++;
  599.     return result;
  600. }
  601.  
  602. //--------------------------------------------------------------------------------------------------
  603. // CDSSpec::GetDirectoryExtensionType
  604. //--------------------------------------------------------------------------------------------------
  605.  
  606. Boolean CDSSpec::GetDirectoryExtensionType(OSType myExtType, Boolean& isRString, CStr255& dirSysName)
  607. {
  608.     Boolean found = FALSE;
  609.     
  610.     DirExtTypeEntry* defaultDirExtType;
  611.     
  612.     CDirExtTypeTableIterator iter(kDirExtTypeTableID);
  613.     for (DirExtTypeEntry* dirExtType = iter.FirstDirExtType(); iter.More(); dirExtType = iter.NextDirExtType())
  614.     {
  615.         defaultDirExtType = dirExtType;
  616.         if (myExtType == dirExtType->extType)
  617.         {
  618.             found = TRUE;
  619.             isRString = dirExtType->isRString;
  620.             dirSysName = CStr255(dirExtType->dirSysName);
  621.             break;
  622.         }
  623.     }
  624.     
  625.     if (!found)
  626.     {
  627.         isRString = defaultDirExtType->isRString;
  628.         dirSysName = CStr255(defaultDirExtType->dirSysName);
  629.     }
  630.     
  631.     return found;
  632. }
  633.  
  634. //--------------------------------------------------------------------------------------------------
  635. // CDSSpec::AddressToString
  636. //--------------------------------------------------------------------------------------------------
  637.  
  638. void CDSSpec::AddressToString(CStr255& theString)
  639. {
  640.     OSType myExtType = this->GetExtensionType();
  641.     CStr255 recName(GetRecordName());
  642.  
  643.     Boolean isRString;
  644.     CStr255 dirSysName;
  645.     
  646.     Boolean found = GetDirectoryExtensionType(myExtType, isRString, dirSysName);
  647.     if (found)
  648.     {
  649.         if (isRString)
  650.         {
  651.             CStr255 dirName(GetDirectoryName());
  652.             if (dirName.Length())
  653.             {
  654.                 dirName = "<" + dirName + '>';
  655.                 if (dirName == dirSysName)
  656.                     dirName.Empty();    // don't include redundant directory names
  657.             }
  658.             theString = recName + dirSysName + dirName + CStr255(OCERToPString((RString *)fDSSpec.extensionValue));
  659.         }
  660.         else
  661.         {
  662.             switch (myExtType)
  663.             {
  664.                 // PowerShare
  665.                 case kOCEentnXtn:
  666.                     {
  667.                         CStr255 pathName;
  668.                         GetPathName(pathName);
  669.                         theString = recName + dirSysName + pathName;
  670.                         break;
  671.                     }
  672.  
  673.                 // AppleTalk
  674.                 case kOCEalanXtn:
  675.                     {
  676.                         Ptr ext = (Ptr)fDSSpec.extensionValue;
  677.                         CStr31 name((StringPtr)fDSSpec.extensionValue);
  678.                         CStr31 zone((StringPtr)(&ext[0] + ext[0] + 1 + ext[ext[0] + 1] + 1));
  679.                             // length of 1st pstring + length byte + length of 2nd pstring + length byte
  680.                         theString.fStr[0] = sprintf((char*) & theString.fStr[1], "%s%s%s@%s", 
  681.                                                     (const char*)recName, (const char*)dirSysName, 
  682.                                                     (const char*)name, (const char*)zone);
  683.                         break;
  684.                     }
  685.  
  686.                 // Direct Dialup
  687.                 case kOCEaphnXtn:
  688.                     {
  689.                         PhoneNumberInfo* phoneInfo = this->UnpackDirectDialupInfo();
  690.                         if (phoneInfo)
  691.                         {
  692.                             if (phoneInfo->fSubType == kOCEUseHandyDial)
  693.                                 theString.fStr[0] = sprintf((char*) & theString.fStr[1], "%s%s%s(%s)%s", 
  694.                                                             (const char*)recName, (const char*)dirSysName, 
  695.                                                             (const char*)phoneInfo->fCountryCode, 
  696.                                                             (const char*)phoneInfo->fAreaCode, 
  697.                                                             (const char*)phoneInfo->fPhoneNumber);
  698.                             else if (phoneInfo->fSubType == kOCEDontUseHandyDial)
  699.                                 theString.fStr[0] = sprintf((char*) & theString.fStr[1], "%s%s%s", 
  700.                                                             (const char*)recName, (const char*)dirSysName, 
  701.                                                             (const char*)phoneInfo->fDirectDial);
  702.                             DisposeIfPtr((Ptr)phoneInfo);
  703.                         }
  704.                         break;
  705.                     }
  706.  
  707.                 // Fax
  708.                 case 'TFAX':
  709.                     {
  710.                         PhoneNumberInfo* phoneInfo = this->UnpackSTFFaxInfo();
  711.                         if (phoneInfo)
  712.                         {
  713.                             if (phoneInfo->fSubType == 1)
  714.                                 theString.fStr[0] = sprintf((char*) & theString.fStr[1], "%s%s%s(%s)%s", 
  715.                                                             (const char*)recName, (const char*)dirSysName, 
  716.                                                             (const char*)phoneInfo->fCountryCode, 
  717.                                                             (const char*)phoneInfo->fAreaCode, 
  718.                                                             (const char*)phoneInfo->fPhoneNumber);
  719.                             else
  720.                                 theString.fStr[0] = sprintf((char*) & theString.fStr[1], "%s%s%s", 
  721.                                                             (const char*)recName, (const char*)dirSysName, 
  722.                                                             (const char*)phoneInfo->fDirectDial);
  723.                             DisposeIfPtr((Ptr)phoneInfo);
  724.                         }
  725.                         break;
  726.                     }
  727.  
  728.                 default:
  729.                     break;
  730.             }
  731.         }
  732.     }
  733.     else if (theString.Length() == 0)
  734.         theString = recName + dirSysName;
  735. }
  736.  
  737. //--------------------------------------------------------------------------------------------------
  738. // CDSSpec::ParseDirectDialupAddress
  739. //--------------------------------------------------------------------------------------------------
  740.  
  741. void CDSSpec::ParseDirectDialupAddress(CStr255& dsExtValue)
  742. {
  743.     MAVolatileInit(PhoneNumberInfo * , phoneInfo, NULL);
  744.     MAVolatileInit(Ptr, phoneNumberStr, NULL);
  745.     FailInfo fi;
  746.     Try(fi)
  747.     {
  748.         phoneInfo = (PhoneNumberInfo *)NewPtrClear(sizeof(PhoneNumberInfo));
  749.         phoneInfo->fSubType = kOCEDontUseHandyDial;
  750.         // look for an area code
  751.         unsigned char startChar = dsExtValue.Pos("(", 1);
  752.         unsigned char endChar = 0;
  753.         if (startChar)
  754.         {
  755.             endChar = dsExtValue.Pos(")", startChar) + 1;
  756.             phoneInfo->fSubType = kOCEUseHandyDial;
  757.             phoneInfo->fCountryCode = dsExtValue.Copy(1, startChar - 1);
  758.             phoneInfo->fAreaCode = dsExtValue.Copy(startChar + 1, endChar - startChar - 2);
  759.             phoneInfo->fPhoneNumber = dsExtValue.Copy(endChar, dsExtValue.Length());
  760.         }
  761.         else
  762.         {
  763.             phoneInfo->fDirectDial = dsExtValue;
  764.         }
  765.         phoneNumberStr = NewPtrClear(sizeof(PhoneNumberInfo) + sizeof(ProtoRString));
  766.         Ptr ext = (Ptr)(phoneNumberStr + sizeof(ProtoRString));
  767.         Ptr startExt = ext;
  768.         *(short*)ext = phoneInfo->fSubType;
  769.         ext += sizeof(short);
  770.         PackRString(ext, phoneInfo->fCountryCode);
  771.         PackRString(ext, phoneInfo->fAreaCode);
  772.         PackRString(ext, phoneInfo->fPhoneNumber);
  773.         PackRString(ext, phoneInfo->fPostFix);
  774.         PackRString(ext, phoneInfo->fDirectDial);
  775.         ((RStringPtr)phoneNumberStr)->charSet = smRoman;
  776.         ((RStringPtr)phoneNumberStr)->dataLength = ext - startExt;
  777.  
  778.         fDSSpec.extensionValue = NewPtrClear((sizeof(RString) * 2) + sizeof(CStr31));
  779.         ext = fDSSpec.extensionValue;
  780.         startExt = ext;
  781.         PackRString(ext, (RStringPtr)phoneNumberStr);
  782.         PackRString(ext, gEmptyString);            // reserved, modem string
  783.         PackString(ext, "InMail_Queue");        // "InMail_Queue"
  784.         fDSSpec.extensionSize = ext - startExt;
  785.  
  786.         DisposeIfPtr((Ptr)phoneInfo);
  787.         DisposeIfPtr((Ptr)phoneNumberStr);
  788.         fi.Success();
  789.     }
  790.     else
  791.     {
  792.         DisposeIfPtr((Ptr)phoneInfo);
  793.         DisposeIfPtr((Ptr)phoneNumberStr);
  794.         fi.ReSignal();
  795.     }
  796. }
  797.  
  798. //--------------------------------------------------------------------------------------------------
  799. // CDSSpec::ParseAppleTalkAddress
  800. //--------------------------------------------------------------------------------------------------
  801.  
  802. void CDSSpec::ParseAppleTalkAddress(CStr255& dsExtValue)
  803. {
  804.     Ptr theEntity = NewPtrClear(sizeof(EntityName));
  805.     // Parses the extension string into an AppleTalk EntityName.
  806.     unsigned char startChar = dsExtValue.Pos("@", 1);
  807.     CStr31 objStr;
  808.     CStr31 zoneStr = "*";
  809.     CStr31 typeStr = kIPMWSReceiverNBPType;
  810.     if (startChar > 0)
  811.     {
  812.         objStr = dsExtValue.Copy(1, startChar - 1);
  813.         zoneStr = dsExtValue.Copy(startChar + 1, dsExtValue.Length());
  814.     }
  815.     NBPSetEntity(theEntity, objStr, typeStr, zoneStr);
  816.     fDSSpec.extensionValue = theEntity;    // caller will toss the extension value pointer
  817.     fDSSpec.extensionSize = objStr.Length() + typeStr.Length() + zoneStr.Length() + 3;
  818.     // Get the record type from the 'rast' resource and stuff it in
  819.     Handle rastHandle = MAGet1Resource('rast', kAppleTalkRecordType);
  820.     FailNILResource(rastHandle);
  821.     HLock(rastHandle);
  822.     OCECopyRString((RStringPtr) * rastHandle, fRecordID.local.recordType, kRStringMaxBytes);
  823.     ReleaseResource(rastHandle);
  824.     // Setup the RLI
  825.     fRLI.discriminator.signature = 'atlk';
  826.     fRLI.discriminator.misc = kDirDSAMKind;
  827.     fRLI.dNodeNumber = 0;
  828. }
  829.  
  830. //--------------------------------------------------------------------------------------------------
  831. // CDSSpec::ParsePowerShareAddress
  832. //--------------------------------------------------------------------------------------------------
  833.  
  834. void CDSSpec::ParsePowerShareAddress(CStr31& dsDirName,
  835.                                      CStr255& dsExtValue)
  836. {
  837.     // Parses a path name to a catalog record and sets the fRLI to point to it.
  838.     MAVolatileInit(short, numParts, 1);
  839.     MAVolatileInit(short, partIndex, 15);
  840.     MAVolatileInit(DirParamBlockPtr, pb, NULL);
  841.     MAVolatileInit(PackedPathNamePtr, thePackedPath, NULL);
  842.     RStringPtr parts[16];
  843.     BlockSet((Ptr)&parts[0], sizeof(parts), 0);
  844.     FailInfo fi;
  845.     Try(fi)
  846.     {
  847.         // Get the directory name from the start of the path
  848.         dsDirName = dsExtValue;
  849.         unsigned char startChar = dsExtValue.Pos(":", 1);
  850.         if (startChar > 0)
  851.         {
  852.             dsDirName = dsExtValue.Copy(1, startChar - 1);
  853.             dsExtValue.Delete(1, startChar);
  854.         }
  855.         OCEPToRString(dsDirName, smRoman, (RStringPtr)fRLI.directoryName, kRStringMaxBytes);
  856.         // get the discriminator
  857.         CCatalogs theCatalogs;
  858.         theCatalogs.FindCatalogByName(fRLI.directoryName, kDirADAPKind, fRLI.discriminator);
  859.         // create a packed path name
  860.         startChar = dsExtValue.Pos(":", 1);
  861.         while ((startChar > 0) && (partIndex > 0))
  862.         {
  863.             CStr31 pathPart = dsExtValue.Copy(1, startChar - 1);
  864.             dsExtValue.Delete(1, startChar);
  865.             startChar = dsExtValue.Pos(":", 1);
  866.             parts[partIndex] = (RStringPtr)NewPtr(sizeof(RString));
  867.             OCEPToRString(pathPart, smRoman, parts[partIndex], kRStringMaxBytes);
  868.             partIndex--;
  869.             numParts++;
  870.         }
  871.         parts[partIndex] = (RStringPtr)NewPtr(sizeof(RString));
  872.         OCEPToRString(dsExtValue, smRoman, parts[partIndex], kRStringMaxBytes);
  873.         MABlockMove(&parts[partIndex], &parts[0], numParts * sizeof(RStringPtr));
  874.         unsigned short packedPathSize = OCEPackedPathNameSize(parts, numParts);
  875.         thePackedPath = (PackedPathNamePtr)NewPtr(packedPathSize);
  876.         FailOSErr(OCEPackPathName(parts, numParts, thePackedPath, packedPathSize));
  877.  
  878.         pb = (DirParamBlockPtr)NewPtrClear(sizeof(DirParamBlock));
  879.         gMailing->GetAOCEIdentity(pb->mapPathNameToDNodeNumberPB.identity, FALSE);
  880.         pb->mapPathNameToDNodeNumberPB.directoryName = fRLI.directoryName;
  881.         pb->mapPathNameToDNodeNumberPB.discriminator = fRLI.discriminator;
  882.         pb->mapPathNameToDNodeNumberPB.path = thePackedPath;
  883.         FailOSErr(DirMapPathNameToDNodeNumber(pb, FALSE));
  884.         fRLI.dNodeNumber = pb->mapPathNameToDNodeNumberPB.dNodeNumber;
  885.         thePackedPath = (PackedPathNamePtr)DisposeIfPtr((Ptr)thePackedPath);
  886.         for (short pi = 0; pi < numParts; pi++)
  887.             parts[pi] = (RStringPtr)DisposeIfPtr((Ptr)parts[pi]);
  888.         pb = (DirParamBlockPtr)DisposeIfPtr((Ptr)pb);
  889.         fi.Success();
  890.     }
  891.     else
  892.     {
  893.         thePackedPath = (PackedPathNamePtr)DisposeIfPtr((Ptr)thePackedPath);
  894.         for (short pi = 0; pi < numParts; pi++)
  895.             parts[pi] = (RStringPtr)DisposeIfPtr((Ptr)parts[pi]);
  896.         pb = (DirParamBlockPtr)DisposeIfPtr((Ptr)pb);
  897.         fi.ReSignal();
  898.     }
  899. }
  900.  
  901. //--------------------------------------------------------------------------------------------------
  902. // CDSSpec::ParseFaxSTFAddress
  903. //--------------------------------------------------------------------------------------------------
  904.  
  905. void CDSSpec::ParseFaxSTFAddress(CStr31& dsRecName,
  906.                                 CStr255& dsExtValue)
  907. {
  908.     // Parses a phone number string into a format for the STF fax PMSAM.
  909.     MAVolatileInit(PhoneNumberInfo * , phoneInfo, NULL);
  910.     MAVolatileInit(Ptr, phoneNumberStr, NULL);
  911.     FailInfo fi;
  912.     Try(fi)
  913.     {
  914.         phoneInfo = (PhoneNumberInfo *)NewPtrClear(sizeof(PhoneNumberInfo));
  915.         // look for an area code
  916.         unsigned char startChar = dsExtValue.Pos("(", 1);
  917.         unsigned char endChar = 0;
  918.         long useSmartDialing = 0;
  919.         if (startChar)
  920.         {
  921.             useSmartDialing = 1;
  922.             endChar = dsExtValue.Pos(")", startChar) + 1;
  923.             phoneInfo->fCountryCode = dsExtValue.Copy(1, startChar - 1);
  924.             phoneInfo->fAreaCode = dsExtValue.Copy(startChar + 1, endChar - startChar - 2);
  925.             phoneInfo->fPhoneNumber = dsExtValue.Copy(endChar, dsExtValue.Length());
  926.         }
  927.         else
  928.         {
  929.             phoneInfo->fDirectDial = dsExtValue;
  930.             phoneInfo->fPhoneNumber = dsExtValue;
  931.         }
  932.         phoneNumberStr = NewPtrClear(sizeof(PhoneNumberInfo) + sizeof(ProtoRString));
  933.         Ptr ext = (Ptr)(phoneNumberStr + sizeof(ProtoRString));
  934.         Ptr startExt = ext;
  935.         PackRString(ext, phoneInfo->fDirectDial);
  936.         PackRString(ext, phoneInfo->fCountryCode);
  937.         PackRString(ext, phoneInfo->fAreaCode);
  938.         PackRString(ext, phoneInfo->fPhoneNumber);
  939.         PackRString(ext, dsRecName);
  940.         *(long*)ext = useSmartDialing;
  941.         ext += sizeof(long);
  942.         ((RStringPtr)phoneNumberStr)->charSet = smRoman;
  943.         long theSize = ext - startExt;
  944.         ((RStringPtr)phoneNumberStr)->dataLength = theSize;
  945.         theSize += sizeof(ProtoRString);
  946.         fDSSpec.extensionValue = phoneNumberStr;
  947.         fDSSpec.extensionSize = theSize;
  948.         phoneInfo = (PhoneNumberInfo *)DisposeIfPtr((Ptr)phoneInfo);
  949.         fi.Success();
  950.     }
  951.     else
  952.     {
  953.         phoneInfo = (PhoneNumberInfo *)DisposeIfPtr((Ptr)phoneInfo);
  954.         fi.ReSignal();
  955.     }
  956. }
  957.  
  958. //--------------------------------------------------------------------------------------------------
  959. // CDSSpec::ParseRStringAddress
  960. //--------------------------------------------------------------------------------------------------
  961.  
  962. void CDSSpec::ParseRStringAddress(CStr255& dsExtValue)
  963. {
  964.     // The default MSAM address format is an RString in the extensionValue.
  965.     fDSSpec.extensionValue = NewPtr(sizeof(RString));
  966.     OCEPToRString(dsExtValue, smRoman, (RStringPtr)fDSSpec.extensionValue, kRStringMaxBytes);
  967.     fDSSpec.extensionSize = sizeof(ProtoRString) + ((RStringPtr)fDSSpec.extensionValue)->dataLength;
  968. }
  969.  
  970. //--------------------------------------------------------------------------------------------------
  971. // CDSSpec::StringToAddress
  972. //--------------------------------------------------------------------------------------------------
  973.  
  974. void CDSSpec::StringToAddress(CStr255& theString)
  975. {
  976.     MAVolatileInit(RStringPtr, recName, NULL);
  977.     MAVolatileInit(RStringPtr, recType, NULL);
  978.     MAVolatileInit(RStringPtr, dirName, NULL);
  979.     fDSSpec.extensionValue = NULL;
  980.     fUnpacked = FALSE;
  981.     FailInfo fi;
  982.     Try(fi)
  983.     {
  984.         unsigned short theSize = 0;
  985.         PackedRLIPtr thePackedRLI = NULL;
  986.         CStr255 str;
  987.         recName = (RStringPtr)NewPtrClear(sizeof(RString));
  988.         recType = (RStringPtr)NewPtrClear(sizeof(RString));
  989.         dirName = (RStringPtr)NewPtrClear(sizeof(RString));
  990.  
  991.         fRLI.directoryName = (DirectoryNamePtr)dirName;
  992.         fRLI.discriminator.signature = '    ';
  993.         fRLI.discriminator.misc = 0;
  994.         fRLI.dNodeNumber = 0;
  995.         fRLI.path = NULL;
  996.  
  997.         fRecordID.local.recordName = recName;
  998.         fRecordID.local.recordType = recType;
  999.         fRecordID.local.cid = *OCENullCID();
  1000.         fRecordID.rli = NULL;
  1001.  
  1002.         fDSSpec.entitySpecifier = &fRecordID;
  1003.         fDSSpec.extensionType = '\?\?\?\?';
  1004.         fDSSpec.extensionSize = 0;
  1005.         fDSSpec.extensionValue = NULL;
  1006.  
  1007.         unsigned char startChar = theString.Pos("<", 1);
  1008.         unsigned char endChar = theString.Pos(">", startChar) + 1;
  1009.         CStr31 dsRecName = theString.Copy(1, startChar - 1);
  1010.         CStr255 dsDirType = theString.Copy(startChar, endChar - startChar);
  1011.         CStr255 dsExtValue = theString.Copy(endChar, theString.Length());
  1012.         CStr31 dsDirName;
  1013.         startChar = dsExtValue.Pos("<", 1);
  1014.         if (startChar)
  1015.         {
  1016.             // see if there is a directory name
  1017.             endChar = dsExtValue.Pos(">", startChar) + 1;
  1018.             dsDirName = dsExtValue.Copy(2, endChar - 3);
  1019.             dsExtValue = dsExtValue.Copy(endChar, dsExtValue.Length());
  1020.         }
  1021.  
  1022.         OCEPToRString(dsRecName, smRoman, fRecordID.local.recordName, kRStringMaxBytes);
  1023.  
  1024.         CDirExtTypeTableIterator iter(kDirExtTypeTableID);
  1025.         DirExtTypeEntry * defaultDirExtType = 0;
  1026.         for (DirExtTypeEntry * dirExtType = iter.FirstDirExtType(); iter.More(); dirExtType = iter.NextDirExtType())
  1027.         {
  1028.  
  1029.             defaultDirExtType = dirExtType;
  1030.  
  1031.             if (dsDirType == dirExtType->dirSysName)
  1032.             {
  1033.                 fDSSpec.extensionType = dirExtType->extType;
  1034.                 if (dsDirName.Length() == 0)
  1035.                 {
  1036.                     // get the default directory name
  1037.                     dsDirName = dirExtType->dirSysName;
  1038.                     // get rid of the <> around the name
  1039.                     dsDirName.Delete(dsDirName.Length(), 1);
  1040.                     dsDirName.Delete(1, 1);
  1041.                 }
  1042.                 OCECToRString(kUserRecTypeBody, smRoman, fRecordID.local.recordType, kRStringMaxBytes);
  1043.                 OCEPToRString(dsDirName, smRoman, (RStringPtr)fRLI.directoryName, kRStringMaxBytes);
  1044.                 fRLI.discriminator.signature = fDSSpec.extensionType;
  1045.                 fRLI.discriminator.misc = 0;
  1046.                 fRLI.dNodeNumber = 0;
  1047.  
  1048.                 switch (fDSSpec.extensionType)
  1049.                 {
  1050.                     case kOCEentnXtn:
  1051.                         this->ParsePowerShareAddress(dsDirName, dsExtValue);
  1052.                         break;
  1053.  
  1054.                     case kOCEalanXtn:
  1055.                         this->ParseAppleTalkAddress(dsExtValue);
  1056.                         break;
  1057.  
  1058.                     case kOCEaphnXtn:
  1059.                         this->ParseDirectDialupAddress(dsExtValue);
  1060.                         break;
  1061.  
  1062.                     case 'TFAX':
  1063.                         this->ParseFaxSTFAddress(dsRecName, dsExtValue);
  1064.  
  1065.                     default:
  1066.                         this->ParseRStringAddress(dsExtValue);
  1067.                         break;
  1068.                 }
  1069.                 break;
  1070.             }
  1071.         }
  1072.         this->Pack();
  1073.         recName = (RStringPtr)DisposeIfPtr((Ptr)recName);
  1074.         recType = (RStringPtr)DisposeIfPtr((Ptr)recType);
  1075.         dirName = (RStringPtr)DisposeIfPtr((Ptr)dirName);
  1076.         fDSSpec.extensionValue = DisposeIfPtr(fDSSpec.extensionValue);
  1077.         this->Unpack();
  1078.         fi.Success();
  1079.     }
  1080.     else
  1081.     {
  1082.         recName = (RStringPtr)DisposeIfPtr((Ptr)recName);
  1083.         recType = (RStringPtr)DisposeIfPtr((Ptr)recType);
  1084.         dirName = (RStringPtr)DisposeIfPtr((Ptr)dirName);
  1085.         fDSSpec.extensionValue = DisposeIfPtr(fDSSpec.extensionValue);
  1086.         fi.ReSignal();
  1087.     }
  1088. }
  1089.  
  1090. //========================================================================================
  1091. // CLASS MMailable
  1092. //========================================================================================
  1093. #undef Inherited
  1094.  
  1095. #pragma segment MAOpen
  1096. MA_DEFINE_CLASS_M0(MMailable);
  1097.  
  1098. //----------------------------------------------------------------------------------------
  1099. // MMailable constructor
  1100. //----------------------------------------------------------------------------------------
  1101. #pragma segment MAOpen
  1102.  
  1103. MMailable::MMailable()
  1104. {
  1105.     fLetter = NULL;
  1106.     fMailCreator = gDispatcher->fCreator;        // default letter creator
  1107.     fMailType = gMailing->fMainLetterFileType;    // default letter type
  1108.     fSendFormats = kSMPNativeMask + kSMPImageMask + kSMPStandardInterchangeMask;
  1109. }
  1110.  
  1111. //----------------------------------------------------------------------------------------
  1112. // MMailable::Free: 
  1113. //----------------------------------------------------------------------------------------
  1114. #pragma segment MAClose
  1115.  
  1116. MMailable::~MMailable()
  1117. {
  1118.     fLetter = (TLetter*) FreeIfObject(fLetter);
  1119. }
  1120.  
  1121. //----------------------------------------------------------------------------------------
  1122. // MMailable::AddNativeMailContent
  1123. //----------------------------------------------------------------------------------------
  1124. #pragma segment AMailerRes
  1125.  
  1126. void MMailable::AddNativeMailContent(Boolean& okToSend)
  1127. {
  1128.     FailNonObject(fLetter);
  1129.     fLetter->AddNativeMailContent(okToSend);
  1130. }
  1131.  
  1132. //----------------------------------------------------------------------------------------
  1133. // MMailable::AddSnapshotMailContent
  1134. //----------------------------------------------------------------------------------------
  1135. #pragma segment AMailerRes
  1136.  
  1137. void MMailable::AddSnapshotMailContent(Boolean& okToSend)
  1138. {
  1139.     FailNonObject(fLetter);
  1140.     fLetter->AddSnapshotMailContent(okToSend);
  1141. }
  1142.  
  1143. //----------------------------------------------------------------------------------------
  1144. // MMailable::AddStandardMailContent
  1145. //----------------------------------------------------------------------------------------
  1146. #pragma segment AMailerRes
  1147.  
  1148. void MMailable::AddStandardMailContent(Boolean& okToSend)
  1149. {
  1150.     FailNonObject(fLetter);
  1151.     fLetter->AddStandardMailContent(okToSend);
  1152. }
  1153.  
  1154. //----------------------------------------------------------------------------------------
  1155. // MMailable::CountContainedMailers: 
  1156. //----------------------------------------------------------------------------------------
  1157. #pragma segment OSLDispatchRes
  1158.  
  1159. long MMailable::CountContainedMailers()
  1160. {
  1161.     long count = 0;
  1162.     
  1163.     if (fLetter)
  1164.         count = fLetter->CountContainedMailers();
  1165.     
  1166.     return count;
  1167. }
  1168.  
  1169. //----------------------------------------------------------------------------------------
  1170. // MMailable::DoAECreateMailer
  1171. //----------------------------------------------------------------------------------------
  1172. #pragma segment AMailerRes
  1173.  
  1174. void MMailable::DoAECreateMailer(TAppleEvent* message,
  1175.                                  TAppleEvent* reply)
  1176. {
  1177.     if (!fLetter)
  1178.         DoMakeLetter();
  1179.     FailNonObject(fLetter);
  1180.     fLetter->DoAECreateMailer(message, reply);
  1181. }
  1182.  
  1183. //----------------------------------------------------------------------------------------
  1184. // MMailable::DoAECreateReply
  1185. //----------------------------------------------------------------------------------------
  1186. #pragma segment AMailerRes
  1187.  
  1188. void MMailable::DoAECreateReply(TAppleEvent* message,
  1189.                                 TAppleEvent* reply)
  1190. {
  1191.     if (!fLetter)
  1192.         DoMakeLetter();
  1193.     FailNonObject(fLetter);
  1194.     fLetter->DoAECreateReply(message, reply);
  1195. }
  1196.  
  1197. //----------------------------------------------------------------------------------------
  1198. // MMailable::DoAESend
  1199. //----------------------------------------------------------------------------------------
  1200. #pragma segment AMailerRes
  1201.  
  1202. void MMailable::DoAESend(TAppleEvent* message,
  1203.                          TAppleEvent* reply)
  1204. {
  1205.     FailNonObject(fLetter);
  1206.     fLetter->DoAESend(message, reply);
  1207. }
  1208.  
  1209. //----------------------------------------------------------------------------------------
  1210. // MMailable::DoMailMenuCommand: 
  1211. //----------------------------------------------------------------------------------------
  1212. #pragma segment MASelCommand
  1213.  
  1214. Boolean MMailable::DoMailMenuCommand(CommandNumber aCommandNumber)
  1215. {
  1216.     Boolean handled = FALSE;
  1217.     
  1218.     if ((aCommandNumber == cAddMailer) && !fLetter)
  1219.         DoMakeLetter();
  1220.  
  1221.     if (fLetter)
  1222.         handled = fLetter->DoMailMenuCommand(aCommandNumber);
  1223.     
  1224.     return handled;
  1225. }
  1226.  
  1227. //----------------------------------------------------------------------------------------
  1228. // MMailable::DoMakeLetter
  1229. //----------------------------------------------------------------------------------------
  1230. #pragma segment AMailerRes
  1231.  
  1232. void MMailable::DoMakeLetter()
  1233. {
  1234.     // The default implementation makes a TFileBasedLetter, which is intended
  1235.     // to work with a TFileBasedDocument. If your document is not a subclass of
  1236.     // TFileBasedDocument, override this method to make a TLetter subclass that
  1237.     // works with your document. 
  1238.     
  1239.     if (!fLetter)
  1240.     {
  1241.         TFileBasedLetter* it = new TFileBasedLetter;
  1242.         it->IFileBasedLetter(this);
  1243.         fLetter = it;
  1244.     }
  1245. }
  1246.  
  1247. //----------------------------------------------------------------------------------------
  1248. // MMailable::DoSetupMailMenus: 
  1249. //----------------------------------------------------------------------------------------
  1250. #pragma segment MADocumentRes
  1251.  
  1252. void MMailable::DoSetupMailMenus()
  1253. {
  1254.     if (HasAOCEToolBox())
  1255.     {
  1256.         if (!fLetter)
  1257.         {
  1258.             SetIndividualCommandName(cAddMailer, kAOCEStrings, kAddMailerCmdName);
  1259.             Enable(cAddMailer, TRUE);
  1260.         }
  1261.         else
  1262.             fLetter->DoSetupMailMenus();
  1263.     }
  1264. }
  1265.  
  1266. //----------------------------------------------------------------------------------------
  1267. // MMailable::FindLetter
  1268. //----------------------------------------------------------------------------------------
  1269. #pragma segment AMailerRes
  1270.  
  1271. TDocument* MMailable::FindLetter(Handle /*itsSpec*/)
  1272. {
  1273.     return NULL;
  1274. }
  1275.  
  1276. //----------------------------------------------------------------------------------------
  1277. // MMailable::GetIndContainedMailer
  1278. //----------------------------------------------------------------------------------------
  1279. #pragma segment AMailerRes
  1280.  
  1281. MScriptableObject* MMailable::GetIndContainedMailer(long index)
  1282. {
  1283.     MScriptableObject* mailer = NULL;
  1284.     
  1285.     if (fLetter)
  1286.         mailer = fLetter->GetIndContainedMailer(index);
  1287.     
  1288.     return mailer;
  1289. }
  1290.  
  1291. //----------------------------------------------------------------------------------------
  1292. // MMailable::GetSendFormats
  1293. //----------------------------------------------------------------------------------------
  1294. #pragma segment AMailerRes
  1295.  
  1296. unsigned long MMailable::GetSendFormats()
  1297. {
  1298.     return fSendFormats;
  1299. }
  1300.  
  1301. //----------------------------------------------------------------------------------------
  1302. // MMailable::HasMailer
  1303. //----------------------------------------------------------------------------------------
  1304. #pragma segment AMailerRes
  1305.  
  1306. Boolean MMailable::HasMailer()
  1307. {
  1308.     return (fLetter != NULL) ? fLetter->HasMailer() : NULL;
  1309. }
  1310.  
  1311. //----------------------------------------------------------------------------------------
  1312. // MMailable::ImageDocumentForLetter
  1313. //----------------------------------------------------------------------------------------
  1314. #pragma segment AMailerRes
  1315.  
  1316. void MMailable::ImageDocumentForLetter(Boolean /*inColor*/)
  1317. {
  1318.     // Override to draw your document contents. 
  1319. }
  1320.  
  1321. //----------------------------------------------------------------------------------------
  1322. // MMailable::LetterContentChanged
  1323. //----------------------------------------------------------------------------------------
  1324. #pragma segment AMailerRes
  1325.  
  1326. void MMailable::LetterContentChanged()
  1327. {
  1328.     if (fLetter)
  1329.         fLetter->LetterContentChanged();
  1330. }
  1331.  
  1332. //----------------------------------------------------------------------------------------
  1333. // MMailable::MakeRoomForMailer
  1334. //----------------------------------------------------------------------------------------
  1335. #pragma segment AMailerRes
  1336.  
  1337. void MMailable::MakeRoomForMailer(long amount, Boolean redraw)
  1338. {
  1339.     // This implementation assumes your window's main content view
  1340.     // is a scroller with ID 'SCLR'. If your views are organized
  1341.     // differently, override this method to move your views around. 
  1342.     
  1343.     if (fLetter)
  1344.     {
  1345.         TWindow* mailerWindow = fLetter->GetMailerWindow();
  1346.         FailNonObject(mailerWindow);
  1347.         TView* theView = mailerWindow->FindSubView('SCLR');
  1348.         FailNonObject(theView);
  1349.         VRect viewFrame(theView->GetFrame());
  1350.         viewFrame.top += amount;
  1351.         theView->SetFrame(viewFrame, kDontInvalidate);
  1352.         
  1353.         if (redraw && mailerWindow->Focus())
  1354.         {
  1355.             mailerWindow->ForceRedraw();    // invalidate window
  1356.             
  1357.             // validate mailer view to prevent flash
  1358.             TMailerView* theMailerView = fLetter->GetMailerView();
  1359.             if (theMailerView != NULL)
  1360.             {
  1361.                 CTemporaryRegion visibleRgn;
  1362.                 theMailerView->GetVisibleRegion(visibleRgn);
  1363.                 theMailerView->ValidateRegion(visibleRgn);
  1364.             }
  1365.         }        
  1366.     }
  1367. }
  1368.  
  1369. //----------------------------------------------------------------------------------------
  1370. // MMailable::OpenLetter
  1371. //----------------------------------------------------------------------------------------
  1372. #pragma segment AMailerRes
  1373.  
  1374. void MMailable::OpenLetter()
  1375. {
  1376.     fLetter->OpenLetter();
  1377. }
  1378.  
  1379. //----------------------------------------------------------------------------------------
  1380. // MMailable::ReadLetter
  1381. //----------------------------------------------------------------------------------------
  1382. #pragma segment AMailerRes
  1383.  
  1384. void MMailable::ReadLetter(Boolean forPrinting)
  1385. {
  1386.     if (!fLetter)
  1387.         DoMakeLetter();
  1388.     
  1389.     fLetter->ReadLetter(forPrinting);
  1390. }
  1391.  
  1392. //----------------------------------------------------------------------------------------
  1393. // MMailable::ReadNativeMailContent
  1394. //----------------------------------------------------------------------------------------
  1395. #pragma segment AMailerRes
  1396.  
  1397. Boolean MMailable::ReadNativeMailContent()
  1398. {
  1399.     FailNonObject(fLetter);
  1400.     return fLetter->ReadNativeMailContent();
  1401. }
  1402.  
  1403. //----------------------------------------------------------------------------------------
  1404. // MMailable::ReadStandardMailContent
  1405. //----------------------------------------------------------------------------------------
  1406. #pragma segment AMailerRes
  1407.  
  1408. Boolean MMailable::ReadStandardMailContent()
  1409. {
  1410.     FailNonObject(fLetter);
  1411.     return fLetter->ReadStandardMailContent();
  1412. }
  1413.  
  1414. //----------------------------------------------------------------------------------------
  1415. // MMailable::ReadStandardMailContent
  1416. //----------------------------------------------------------------------------------------
  1417. #pragma segment AMailerRes
  1418.  
  1419. Boolean MMailable::ReadSnapshotMailContent()
  1420. {
  1421.     FailNonObject(fLetter);
  1422.     return fLetter->ReadSnapshotMailContent();
  1423. }
  1424.  
  1425.  
  1426. //----------------------------------------------------------------------------------------
  1427. // MMailable::SetReplyContents
  1428. //----------------------------------------------------------------------------------------
  1429. #pragma segment AMailerRes
  1430.  
  1431. void MMailable::SetReplyContents(TDocument* /*replyToDoc*/)
  1432. {
  1433.     // Override to set up the reply document with contents 
  1434.     // based on the original. 
  1435. }
  1436.  
  1437. //========================================================================================
  1438. // CLASS MMailing
  1439. //========================================================================================
  1440. #undef Inherited
  1441.  
  1442. #pragma segment MAInit
  1443. MA_DEFINE_CLASS_M0(MMailing);
  1444.  
  1445. //----------------------------------------------------------------------------------------
  1446. // MMailing constructor
  1447. //----------------------------------------------------------------------------------------
  1448. #pragma segment MAInit
  1449.  
  1450. MMailing::MMailing()
  1451. {
  1452.     gMailing = this;
  1453. }
  1454.  
  1455. //----------------------------------------------------------------------------------------
  1456. // MMailing::GetAOCEIdentity
  1457. // Note: may return an error if the identity can't be retrieved.
  1458. //----------------------------------------------------------------------------------------
  1459. #pragma segment AMailerRes
  1460.  
  1461. OSErr MMailing::GetAOCEIdentity(AuthIdentity&     theIdentity,
  1462.                                 Boolean            allowInteraction)
  1463. {
  1464.     OSErr                     err;
  1465.     SDPIdentityKind         idKind;
  1466.     AuthGetLocalIdentityPB     pBlock;
  1467.  
  1468.     err = AuthGetLocalIdentity((AuthParamBlockPtr)&pBlock, FALSE);
  1469.     
  1470.     if (err == noErr)
  1471.     {
  1472.         theIdentity = pBlock.theLocalIdentity;
  1473.     }
  1474.     else if (allowInteraction)
  1475.     {
  1476.         FailOSErr(MAInteractWithUser()); 
  1477.         
  1478.         CStr255 localIDPrompt;
  1479.         GetIndString(localIDPrompt, kAOCEStrings, kGetIdentityPrompt);
  1480.         err = SDPPromptForID(&theIdentity, NULL, NULL, localIDPrompt, NULL, 
  1481.             kSDPLocalIdentityMask, &idKind, NULL, 0);
  1482.     }
  1483.     return err;
  1484. }
  1485.  
  1486. //----------------------------------------------------------------------------------------
  1487. // MMailing::DoMailerEvent
  1488. //----------------------------------------------------------------------------------------
  1489. #pragma segment AMailerRes
  1490.  
  1491. Boolean MMailing::DoMailerEvent(TToolboxEvent* event)
  1492. {
  1493.     // Passes events to the standard mail package.
  1494.     // Returns TRUE if the SMP handled the event.
  1495.     
  1496.     Boolean result = FALSE;
  1497.     if (HasAOCEToolBox())
  1498.     {
  1499.         EventRecord theEvent;
  1500.         if (event)
  1501.             theEvent = event->fEventRecord;
  1502.         else
  1503.         {
  1504.             // call the same FrontWindowProc AOCE will call to get our front window
  1505.             WindowRef frontWindowRef = (WindowRef)CallFrontWindowProc(gFrontWindowUPP, 0);
  1506.             TWindow *frontWindow = TWindow::WMgrToWindow(frontWindowRef);
  1507.             if (frontWindow)
  1508.                 frontWindow->Focus();
  1509.                 
  1510.             BlockSet((Ptr) & theEvent, sizeof(EventRecord), 0);
  1511.             GetMouse((CPoint &)theEvent.where);
  1512.             LocalToGlobal((CPoint &)theEvent.where);
  1513.             theEvent.when = TickCount();
  1514.             theEvent.modifiers = 128;
  1515.         }
  1516.  
  1517.         // Don't handle mouse and key events, they are handled by the view.
  1518.         Boolean handleHere = (theEvent.what != mouseDown) && (theEvent.what != mouseUp) && (theEvent.what != keyDown) && (theEvent.what != autoKey);
  1519.         // However, give the mail package a crack at mouse downs that are not in our windows.
  1520.         // This is so it can drag stuff in from other apps.
  1521.         if (theEvent.what == mouseDown)
  1522.         {
  1523.             WindowPtr aWMgrWindow;
  1524.             short whereMouseDown = FindWindow(theEvent.where, &aWMgrWindow);
  1525.             handleHere = handleHere || (TWindow::WMgrToWindow(aWMgrWindow) == NULL);
  1526.         }
  1527.  
  1528.         if (handleHere)
  1529.         {
  1530.             OSErr err = 0;
  1531.             SMPMailerResult whatHappened = 0;
  1532.             
  1533.             err = SMPMailerEvent(&theEvent, &whatHappened, gFrontWindowUPP, (long)this);
  1534.             if ((whatHappened & kSMPCreateCopyWindowMask) || (whatHappened & kSMPDisposeCopyWindowMask))
  1535.                 InvalidateMenuBar();
  1536.  
  1537.             result = (Boolean)(whatHappened & kSMPAppShouldIgnoreEventMask);
  1538.         }
  1539.     }
  1540.     return result;
  1541. }
  1542.  
  1543. //----------------------------------------------------------------------------------------
  1544. // MMailing::DoOpenNextLetter
  1545. //----------------------------------------------------------------------------------------
  1546. #pragma segment AMailerRes
  1547.  
  1548. void MMailing::DoOpenNextLetter(CommandNumber aCommandNumber)
  1549. {
  1550.     FailOSErr(SMPInitMailer(0));
  1551.     AuthIdentity        userIdentity;
  1552.     
  1553.     if (this->GetAOCEIdentity(userIdentity, TRUE) != noErr)
  1554.         return;
  1555.     
  1556.     FailInfo fi;
  1557.     Try(fi)
  1558.     {
  1559.         OSType                 theType = fMainLetterFileType;
  1560.         LetterDescriptor     theLetter;                        
  1561.  
  1562.         FailOSErr(SMPGetNextLetter(&theType, 1, &theLetter)); 
  1563.         
  1564.         TOpenNextLetterCommand* anOpenNextLetterCommand = new TOpenNextLetterCommand;
  1565.         anOpenNextLetterCommand->IOpenNextLetterCommand(aCommandNumber);
  1566.         anOpenNextLetterCommand->fUseAppleEvent = TRUE;
  1567.         gDispatcher->PostCommand(anOpenNextLetterCommand);
  1568.         
  1569.         fi.Success();
  1570.     }
  1571.     else
  1572.     {
  1573.         if (fi.error == kSMPNoNextLetter)
  1574.             StdAlert(phNoNextLetter);
  1575.         else
  1576.             fi.ReSignal();
  1577.     }
  1578. }
  1579.  
  1580. //----------------------------------------------------------------------------------------
  1581. // MMailing::OpenOldLetters
  1582. //----------------------------------------------------------------------------------------
  1583. #pragma segment AMailerRes
  1584.  
  1585. void MMailing::OpenOldLetters(CommandNumber itsOpenCommand,
  1586.                                   const CAEDesc& letterList)
  1587. {
  1588.     // Opens letter documents from the PowerTalk mailbox.
  1589.     // Similar to OpenOld, but here we make the document, give it the letter descriptor,
  1590.     // then make the views. Then TDocument::OpenLetter gets called to read the letter
  1591.     // content.
  1592.  
  1593.     MAVolatileInit(TDocument*, aDocument, NULL);
  1594.     MAVolatileInit(TFile*, aFile, NULL);
  1595.     
  1596.     Size    oldCodeReserve;
  1597.     Size     oldMemReserve;
  1598.     
  1599.     GetReserveSize(oldCodeReserve, oldMemReserve);
  1600.  
  1601.     long numLetters = 0;
  1602.     FailOSErr(AECountItems(letterList, &numLetters));
  1603.     for (short index = 1; index <= numLetters; index++)
  1604.     {
  1605.         FailInfo fi;
  1606.         Try(fi)
  1607.         {
  1608.             {
  1609.                 CTempDesc letterDesc;
  1610.                 DescType ignoreKey;
  1611.                 FailOSErr(AEGetNthDesc(letterList, index, typeLetterDesc, &ignoreKey, letterDesc));
  1612.  
  1613.                 // Set reserve down a little to ensure that we can open existing documents 
  1614.                 SetReserveSize(oldCodeReserve, oldMemReserve / 2);
  1615.  
  1616.                 Handle theLetterSpec = letterDesc.GetDataHandle();
  1617.  
  1618.                 TDocument * otherDoc = this->FindLetter(theLetterSpec);
  1619.  
  1620.                 if (otherDoc)
  1621.                 {
  1622.                     otherDoc->OpenAgain(itsOpenCommand, aDocument);
  1623.                     SetReserveSize(oldCodeReserve, oldMemReserve);
  1624.                 }
  1625.                 else if (this->CanOpenLetter(itsOpenCommand, theLetterSpec))
  1626.                 {
  1627.                     FailNIL(aDocument = gApplication->DoMakeDocument(gApplication->KindOfDocument(itsOpenCommand, aFile), aFile));
  1628.                     
  1629.                     MMailable* mailDoc = MA_DYNAMIC_CAST(MMailable, aDocument);
  1630.                     if (!mailDoc) Failure(minErr, 0);
  1631.                     mailDoc->DoMakeLetter();
  1632.                     TLetter* docLetter = mailDoc->fLetter;
  1633.                     {
  1634.                         // When opening a letter we first tell the letter which desc it should use, then it creates
  1635.                         // its views, including the mailer. After creating the views we tell the letter to load its data.
  1636.                         
  1637.                         LetterDescriptor theDescriptor;
  1638.                         theDescriptor.onDisk = FALSE;
  1639.                         theDescriptor.u.mailboxSpec = **(LetterSpec * *)theLetterSpec;
  1640.                         Handle theDescHdl = NewPermHandle(sizeof(theDescriptor));
  1641.                         **(LetterDescriptor * *)theDescHdl = theDescriptor;
  1642.                         
  1643.                         docLetter->SetLetterDesc(theDescHdl);
  1644.                     
  1645.                         aDocument->DoMakeViews(kForDisplay);
  1646.                         docLetter->OpenLetter();
  1647.                     }
  1648.  
  1649.                     FailSpaceIsLow();            // Fail if the document leaves us with no
  1650.                                                 // memory
  1651.                     // Set the reserve back to where it was 
  1652.                     SetReserveSize(oldCodeReserve, oldMemReserve);
  1653.  
  1654.                     // Don't attempt to show the windows until we're sure we won't fail 
  1655.                     aDocument->DoPostMakeViews(kForDisplay);
  1656.                 }
  1657.                 else
  1658.                     Failure(errNotMyType, 0);
  1659.             }
  1660.             fi.Success();
  1661.         }
  1662.         else // Recover
  1663.         {
  1664.             if (aDocument != NULL)
  1665.                 aDocument = (TDocument *)FreeIfObject(aDocument); // The document will free the file
  1666.             else
  1667.                 aFile = (TFile *)FreeIfObject(aFile);                             // otherwise its our responsibility
  1668.  
  1669.             // Set the reserve back to where it was 
  1670.             SetReserveSize(oldCodeReserve, oldMemReserve);
  1671.  
  1672.             FailNewMessage(fi.error, fi.message, messageOpenFailed);
  1673.         }
  1674.     }
  1675. }
  1676.  
  1677. //----------------------------------------------------------------------------------------
  1678. // MMailing::FindLetter
  1679. //----------------------------------------------------------------------------------------
  1680. #pragma segment AMailerRes
  1681.  
  1682. TDocument* MMailing::FindLetter(Handle itsSpec)
  1683. {
  1684.     CDocumentIterator iter(gDispatcher);
  1685.     MMailable* mailDoc = NULL;
  1686.     
  1687.     for (TDocument * aDocument = iter.FirstDocument(); iter.More(); aDocument = iter.NextDocument())
  1688.         {
  1689.             mailDoc = MA_DYNAMIC_CAST(MMailable, aDocument);
  1690.             if ((mailDoc) && mailDoc->FindLetter(itsSpec))
  1691.                 return aDocument;
  1692.         }
  1693.     return NULL;                                // No document already open
  1694. }
  1695.  
  1696. //----------------------------------------------------------------------------------------
  1697. // MMailing::CanOpenLetter
  1698. //----------------------------------------------------------------------------------------
  1699. #pragma segment AMailerRes
  1700.  
  1701. Boolean MMailing::CanOpenLetter(CommandNumber /* itsCommandNumber */,
  1702.                                     Handle /* itsSpec */)
  1703. {
  1704.     return true;
  1705. }
  1706.  
  1707. //----------------------------------------------------------------------------------------
  1708. // MMailing::IsLetterFileType
  1709. //----------------------------------------------------------------------------------------
  1710. #pragma segment AMailerRes
  1711.  
  1712. Boolean MMailing::IsLetterFileType(OSType theFileType)
  1713. // Return true if theFileType is a letter format this application can open.
  1714. {
  1715.     return (theFileType == fMainLetterFileType);
  1716. }
  1717.  
  1718. //----------------------------------------------------------------------------------------
  1719. // MMailing::TextToDSSpecGlue
  1720. //----------------------------------------------------------------------------------------
  1721. #pragma segment AMailerRes
  1722.  
  1723. pascal OSErr MMailing::TextToDSSpecGlue(DescType /*typeCode*/, const void *dataPtr, Size dataSize, DescType /*toType*/, long /*handlerRefcon*/, AEDesc *result)
  1724. {
  1725.     CAEDesc localDesc;
  1726.     OSErr theErr = gMailing->TextToDSSpec(dataPtr, dataSize, localDesc);
  1727.     *result = (AEDesc &)localDesc;
  1728.     return theErr;
  1729. }
  1730.  
  1731. //----------------------------------------------------------------------------------------
  1732. // MMailing::DSSpecToTextGlue
  1733. //----------------------------------------------------------------------------------------
  1734. #pragma segment AMailerRes
  1735.  
  1736. pascal OSErr MMailing::DSSpecToTextGlue(DescType /*typeCode*/, const void *dataPtr, Size dataSize, DescType /*toType*/, long /*handlerRefcon*/, AEDesc *result)
  1737. {
  1738.     CAEDesc localDesc;
  1739.     OSErr theErr = gMailing->DSSpecToText(dataPtr, dataSize, localDesc);
  1740.     *result = (AEDesc &)localDesc;
  1741.     return theErr;
  1742. }
  1743.  
  1744. //----------------------------------------------------------------------------------------
  1745. // MMailing::TextToDSSpec
  1746. //----------------------------------------------------------------------------------------
  1747. #pragma segment AMailerRes
  1748.  
  1749. OSErr MMailing::TextToDSSpec(const void *textPtr, Size textSize, CAEDesc &result)
  1750. {
  1751.     OSErr resultErr = noErr;
  1752.     FailInfo fi;
  1753.     Try(fi)
  1754.     {
  1755.         CDSSpec theSpec;
  1756.         CStr255 str;
  1757.         str.Length() = (unsigned char)Min(textSize, kStr255Len);
  1758.         MABlockMove(textPtr, &str.fStr[1], str.Length());
  1759.         theSpec.StringToAddress(str);
  1760.         theSpec.GetAEDesc(result);
  1761.         fi.Success();
  1762.     }
  1763.     else
  1764.     {
  1765.         resultErr = errAECoercionFail;
  1766.     }
  1767.     return resultErr;
  1768. }
  1769.  
  1770. //----------------------------------------------------------------------------------------
  1771. // MMailing::DSSpecToText
  1772. //----------------------------------------------------------------------------------------
  1773. #pragma segment AMailerRes
  1774.  
  1775. OSErr MMailing::DSSpecToText(const void *dataPtr, Size /*dataSize*/, CAEDesc &result)
  1776. {
  1777.     OSErr resultErr = noErr;
  1778.     FailInfo fi;
  1779.     Try(fi)
  1780.     {
  1781.         CDSSpec theSpec((PackedDSSpecPtr)dataPtr);
  1782.         CStr255 str;
  1783.         theSpec.AddressToString(str);
  1784.         result.PutString(str);
  1785.         fi.Success();
  1786.     }
  1787.     else
  1788.     {
  1789.         resultErr = errAECoercionFail;
  1790.     }
  1791.     return resultErr;
  1792. }
  1793.  
  1794.  
  1795. //========================================================================================
  1796. // Class TOpenNextLeterCommand
  1797. //========================================================================================
  1798. #undef Inherited
  1799. #define Inherited TCommand
  1800.  
  1801. #pragma segment ConstructorRes
  1802. MA_DEFINE_CLASS_M1(TOpenNextLetterCommand, Inherited);
  1803.  
  1804. //----------------------------------------------------------------------------------------
  1805. // TOpenNextLetterCommand::TOpenNextLetterCommand
  1806. //----------------------------------------------------------------------------------------
  1807. TOpenNextLetterCommand::TOpenNextLetterCommand()
  1808. {
  1809. }
  1810.  
  1811. //----------------------------------------------------------------------------------------
  1812. // TOpenNextLetterCommand::~TOpenNextLetterCommand
  1813. //----------------------------------------------------------------------------------------
  1814. #pragma segment MADestructorRes
  1815. TOpenNextLetterCommand::~TOpenNextLetterCommand()
  1816. {
  1817. }
  1818.  
  1819. //----------------------------------------------------------------------------------------
  1820. // TOpenNextLetterCommand::IOpenNextLetterCommand
  1821. //----------------------------------------------------------------------------------------
  1822. void TOpenNextLetterCommand::IOpenNextLetterCommand(CommandNumber itsCommandNumber)
  1823. {
  1824.     this->ICommand(itsCommandNumber, gDispatcher, kCantUndo, kDoesNotCauseChange, NULL);
  1825. }
  1826.  
  1827. //----------------------------------------------------------------------------------------
  1828. // TOpenNextLetterCommand::DoIt
  1829. //----------------------------------------------------------------------------------------
  1830. void TOpenNextLetterCommand::DoIt()
  1831. {
  1832.     if (HasAOCEToolBox() && gMailing)
  1833.     {        
  1834.         LetterDescriptor     theLetter;                        
  1835.         CTempDesc             theList;
  1836.         OSType                 theType = gMailing->fMainLetterFileType;    
  1837.         
  1838.         FailOSErr(MAInteractWithUser()); 
  1839.         FailOSErr(SMPGetNextLetter(&theType, 1, &theLetter));
  1840.         theList.CreateList();
  1841.         {
  1842.             CTempDesc theLetterDesc;
  1843.             FailOSErr(AECreateDesc(typeLetterDesc, (Ptr)&theLetter.u.mailboxSpec, 
  1844.                 sizeof(LetterSpec), theLetterDesc));
  1845.             theList.PutListItem(0, theLetterDesc);
  1846.         }
  1847.         gMailing->OpenOldLetters(this->fIdentifier, theList);
  1848.     }
  1849. }
  1850.  
  1851. //----------------------------------------------------------------------------------------
  1852. // TOpenNextLetterCommand::MakeAppleEvent
  1853. //----------------------------------------------------------------------------------------
  1854. #pragma segment MACommandRes
  1855.  
  1856. TAppleEvent* TOpenNextLetterCommand::MakeAppleEvent()
  1857. {
  1858.     TAppleEvent*    theOpenNextLetterEvent = NULL;
  1859.     
  1860.     theOpenNextLetterEvent = new TAppleEvent;
  1861.     theOpenNextLetterEvent->IAppleEvent(kAEMailSuite, kAEOpenNextLetter, gServerAddress, kAEWaitReply);
  1862.     
  1863.     return theOpenNextLetterEvent;
  1864. }
  1865.  
  1866.  
  1867. #endif // qPowerTalk
  1868.  
  1869. //----------------------------------------------------------------------------------------
  1870. // End of UMailable.cp
  1871.  
  1872. #pragma segment Inline
  1873.